package dm.ast;

import dm.ast.model.gen.DmConstantGen;
import test.envset.GlobalState;
import test.utility.Randomly;

import java.util.ArrayList;
import java.util.List;

/**
 * @author scy
 * @date 2024/4/17
 */
public class DmSingleJoinExpression extends DmBoolExpression {
    DmASTNode expLeft = null;  //左操作数
    DmASTNode expRight = null;  //右操作数

    DmOperator op = null; //运算符
    public int tag = 0;//用来标记是否带（+）的外连接 0表示不是，1表示（+）连接在左边，2表示连接在右边 目前只考虑一个（+）的情况

    public DmDataType reType = null; //表达式的返回类型

    public void setLeftExp(DmASTNode expression) {
        this.expLeft = expression;
    }

    public void setRightExp(DmASTNode expression) {
        this.expRight = expression;
    }

    public DmOperator getOperator() {
        return op;
    }

    public void setOperator(DmOperator op) {
        this.op = op;
    }

    //交换左操作数，右操作数
    public void changeLeftRight() {
        DmASTNode tmp = expLeft;
        expLeft = expRight;
        expRight = tmp;
    }



    @Override
    public void setWidt() {
        if (expLeft == null) {
            wid_t = 3;
        } else {
            expLeft.setWidt();
            wid_t = expLeft.getWidt();
            if (op != null) {
                wid_t += op.getWidt();
            }
            if (expRight != null) {
                expRight.setWidt();
                wid_t += expRight.getWidt();
            }
        }
    }

    @Override
    public void setDept() {
        if (expLeft == null) {
            dep_t = 1;
        } else {
            expLeft.setDept();
            dep_t = expLeft.getDept();
            if (expRight != null) {
                expRight.setDept();
                if (expRight.getDept() > dep_t) {
                    dep_t = expRight.getDept();
                }
            }
        }
    }

    @Override
    public DmDataType getExpressionType() {
        return reType;
    }

    @Override
    public String toSql() {
        StringBuilder sql = new StringBuilder();
        if (expLeft == null) {
            sql.append(this.getClass().getSimpleName() + getSqlTarget());
        } else {
            if (op.getExpNum() == 2) {  //二元操作符
                if (tag == 1) {
                    sql.append(expLeft.toSql() + "(+)");
                } else {
                    sql.append(expLeft.toSql());
                }
                sql.append(op.toSql());
                if (tag == 2) {
                    sql.append(expRight.toSql() + "(+)");
                } else {
                    sql.append(expRight.toSql());
                }
            }
        }
        return sql.toString();
    }



    @Override
    public void fill(GlobalState globalState) {
        int all = globalState.getCurrentFrom().size();
        int t1 = Randomly.getInteger(0, all);
        int t2 = 0;
        do {
            t2 = Randomly.getInteger(0, all);

        } while (t1 == t2);
        filljoinsingle(globalState.getSelSource(t1), globalState.getSelSource(t2));
        if (expRight instanceof DmConstant) {
            if (expLeft instanceof DmConstant) {
                tag = 0;
            } else {
                tag = 1;
            }
        }
    }


    //没有去除on后边的同名列
    public void filljoinsingle(DmTableSource tab1, DmTableSource tab2) {
        List<DmColumn> cols1 = new ArrayList<>();
        List<DmColumn> cols2 = new ArrayList<>();

        cols1.addAll(tab1.cols);
        cols2.addAll(tab2.cols);

        DmColumn col1 = new DmColumn();
        DmColumn col2 = new DmColumn();

        do {
            col1 = Randomly.fromList(cols1);
            //不选取同名列 暂时只选择类型为INT和CHAR的 因为选取其他类型会有太多报错数据类型不匹配
            if (col1.tag != 1 && (col1.reType == DmDataType.INT || col1.reType == DmDataType.CHAR)) {
                break;
            }
            cols1.remove(col1);
            col1 = null;
        } while (cols1.size() > 0);

        expLeft = col1;
        //没有符合要求的列生成一个
        if (col1 == null) {
            expLeft = DmConstantGen.gen(DmDataType.INT);
            expRight = DmConstantGen.gen(DmDataType.INT);
        } else {
            do {
                col2 = Randomly.fromList(cols2);
                if (col2.reType == col1.reType) {  //类型严格匹配
                    break;  //找到一个，返回
                }
                cols2.remove(col2);
                col2 = null;
            } while (cols2.size() > 0);

            if (col2 != null && expRight == null) {
                expRight = col2;
            } else {
                expRight = DmConstantGen.gen(DmDataType.INT);
            }
        }

    }

    //处理sql错误
    // -4097|单行子查询返回多行
    public void fixErr4097() {
        fixErr4097Low(expLeft);
        fixErr4097Low(expRight);
    }

    public static void fixErr4097Low(DmASTNode exp) {
        if (exp == null) {
            return;
        }
        if (exp instanceof DmSubSelect) {
            ((DmSubSelect) exp).fixErr4097();
        } else if (exp instanceof DmExpression) {
            ((DmExpression) exp).fixErr4097();
        }
    }

}
